<?php

abstract class DbTestCase extends CDbTestCase {

	/**
	 * @var Controller instance of the controller from runController().
	 */
	public $controller = null;

	public static function setUpBeforeClass() {
		if(!isset($_SESSION)) {
			$_SESSION = array();
		}
		$_SERVER['SERVER_NAME'] = 'localhost/task';
		$_SERVER['SCRIPT_NAME'] = 'task/index-test.php';
		$_SERVER['SCRIPT_FILENAME'] = realpath(Yii::app()->getBasePath() . '/../www/index-test.php');
		$_SERVER['DOCUMENT_ROOT'] = realpath('D:\wamp\yii 1.1.8');

		parent::setUpBeforeClass();
	}

	/**
	 * Asserts that the given data pass validation for the given model.
	 * @param CActiveRecord $model the ActiveRecord to validate the data.
	 * @param array $data an array of values to test with. The key is the name
	 * of the attribute while the value is the array of value.
	 */
	public function assertValidatePass($model, $data) {
		try {
			$class = get_class($model);
			$model->clearErrors();
			foreach($data as $attr => $values) {
				for($i = 0, $length = count($values); $i < $length; $i++) {
					$model->$attr = $values[$i];
					$this->assertTrue($model->validate(array($attr)), "$class::$attr should pass validation for [$i] => $values[$i].");
				}
			}
		} catch(PHPUnit_Framework_ExpectationFailedException $e) {
			var_dump($model->getErrors());
			throw $e;
		}
	}

	/**
	 * Asserts that the given data fails validation for the given model.
	 * @param CActiveRecord $model the ActiveRecord to validate the data.
	 * @param array $data an array of values to test with. The key is the name
	 * of the attribute while the value is the array of value.
	 */
	public function assertValidateFail($model, $data) {
		try {
			$class = get_class($model);
			$model->clearErrors();
			foreach($data as $attr => $values) {
				for($i = 0, $length = count($values); $i < $length; $i++) {
					$model->$attr = $values[$i];
					$this->assertFalse($model->validate(array($attr)), "$class::$attr should fail validation for [$i] => $values[$i].");
				}
			}
		} catch(PHPUnit_Framework_ExpectationFailedException $e) {
			var_dump($model->getErrors());
			throw $e;
		}
	}

	private $_generatedString = '';
	private $_stringDictionary = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z');

	/**
	 * Generates a random length of string.
	 * @param int $length length of the string.
	 * @param boolean $reuse whether to reuse the previously generated string.
	 * @return string the generated string.
	 */
	public function generateString($length, $reuse = true) {
		if($length < 0) {
			return $this->_generatedString = '';
		}

		if($reuse) {
			$strlen = strlen($this->_generatedString);

			if($strlen > $length) { //need to cut down
				$this->_generatedString = substr($this->_generatedString, 0, $length);
			} else if($strlen < $length) { //need to add more
				$newLen = $length - $strlen;
				for($i = 0; $i < $newLen; $i++) {
					$this->_generatedString .= $this->_stringDictionary[rand(0, 35)];
				}
			}

			return $this->_generatedString;
		} else {
			$this->_generatedString = '';
			for($i = 0; $i < $length; $i++) {
				$this->_generatedString .= $this->_stringDictionary[rand(0, 35)];
			}
			return $this->_generatedString;
		}
	}

	/**
	 * Runs a controller and sets the $_REQUEST and $_GET parameters.
	 * @param string $route the controllerID/actionID path.
	 * @param array $params associative array of request parameters. This will
	 * be set in $_GET and $_REQUEST. If an index in $_REQUEST already exist, it
	 * will not override.
	 * @param string $method the method that is used to run this controller.
	 * They will be converted to uppercase.
	 * @return Controller the controller associated with the route.
	 */
	public function runController($route, $params=null, $method=null) {
		if(is_array($params)) {
			foreach($params as $key => $value) {
				$_GET[$key] = $value;
				if(!isset($_REQUEST[$key])) {
					$_REQUEST[$key] = $value;
				}
			}
		}

		if(is_string($method)) {
			$_SERVER['REQUEST_METHOD'] = strtoupper($method);
		}

		list($controller, $actionID) = Yii::app()->createController($route);
		$this->controller = $controller;
		$controller->muteRender = true;
		$controller->init();
		$controller->run($actionID);

		return $controller;
	}

	/**
	 * Sets $_POST parameters.
	 * @param array $params associative array of parameters to be set into $_POST.
	 */
	public function setPost($params) {
		foreach($params as $key => $value) {
			$_REQUEST[$key] = $_POST[$key] = $value;
		}
	}

	/**
	 * Empties $_REQUEST, $_POST and $_GET.
	 */
	public function clearRequest() {
		$_REQUEST = $_POST = $_GET = array();
	}

	/**
	 * Logins a User with the specified primary key.
	 * @param int $pk primary key of the User.
	 * @return User ActiveRecord of the logged in user.
	 */
	protected function login($pk = 1) {
		$loginForm = new LoginForm;
		$user = User::model()->findByPk($pk);
		$loginForm->email = $user->email;
		$loginForm->password = 'password'; //according to the fixture
		$this->assertTrue($loginForm->login(), 'Login successful');
		return $user;
	}
	
	protected function logout() {
		Yii::app()->user->logout();
	}

	public static function tearDownAfterClass() {
		Yii::app()->onEndRequest(null);
		parent::tearDownAfterClass();
	}

}